[アップデート] AWS CloudTrail Lake がクエリ結果の S3 へのエクスポートに対応しました
AWS CloudTrail Lake のクエリ結果を Amazon S3 へエクスポートできるようになりました。エクスポートされるデータには、CloudTrail の署名が付きます。このアップデートにより、Amazon QuickSight やサードパーティの BI ツールによる可視化などの連携が行いやすくなります。
試してみる
今回の検証では、次のブログを参考に構築した AWS Organizations 環境の CloudTrail Lake を利用します。
クエリ結果の S3 へのエクスポートとクエリ結果の検証を試します。
クエリ結果の S3 へのエクスポート
事前準備として、クエリ結果を保存する S3 バケットを作成します。
- バケット名
test-cloudtrail-lake-query-results-20221104
- 主な設定内容
- AWS リージョン
ap-northeast-1
- バケットのブロックパブリックアクセス設定
パブリックアクセスを全てブロック
- デフォルトの暗号化
有効にする(SSE-S3)
- バケットポリシー
下記参照
- AWS リージョン
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "cloudtrail.amazonaws.com" }, "Action": [ "s3:PutObject*", "s3:Abort*" ], "Resource": [ "arn:aws:s3:::test-cloudtrail-lake-query-results-20221104", "arn:aws:s3:::test-cloudtrail-lake-query-results-20221104/*" ], "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudtrail:ap-northeast-1:111122223333:eventdatastore/*" } } }, { "Effect": "Allow", "Principal": { "Service": "cloudtrail.amazonaws.com" }, "Action": "s3:GetBucketAcl", "Resource": "arn:aws:s3:::test-cloudtrail-lake-query-results-20221104", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudtrail:ap-northeast-1:111122223333:eventdatastore/*" } } } ] }
S3 バケットを事前に作成せずに、CloudTrail Lake のクエリ実行時に自動で作成することもできます。 上記のバケットポリシーは、自動作成する場合のバケットポリシーと同様の内容にしています。
エクスポート方法は簡単であり、マネジメントコンソール上から行う場合は、クエリ実行時に「結果を S3 に保存」をチェックして保存先の S3 を選択するだけです。
次のクエリを実行してみます。
SELECT eventID, eventTime, eventSource, eventName, RecipientAccountId FROM a2b7ff15-9a9a-4226-aeae-xxxxxexample WHERE eventTime >= '2022-11-03 12:00:00' AND eventTime <= '2022-11-03 13:00:00' ORDER BY eventTime ASC LIMIT 5
マネジメントコンソール上でクエリ結果を確認します。
次に S3 を確認してみると、クエリ結果が保存されています。
result_1.csv.gz
にクエリ結果が保存されており、解凍した CSV ファイルは下記となります。1 行目に実行したクエリの実行時間と実行内容も記載されています。
# Execution Time: 2022-11-04T15:07:11.245281Z Query Statement: SELECT eventID, eventTime, eventSource, eventName, RecipientAccountId FROM a2b7ff15-9a9a-4226-aeae-xxxxxexample WHERE eventTime >= '2022-11-03 12:00:00' AND eventTime <= '2022-11-03 13:00:00' ORDER BY eventTime ASC LIMIT 5 eventID,eventTime,eventSource,eventName,RecipientAccountId 56ec28c5-67a1-47b9-94d1-3acf8aa849bf,2022-11-03 12:01:18.000,s3.amazonaws.com,GetBucketAcl,444455556666 6a491b77-bcda-4577-a76f-7d17f32a84b7,2022-11-03 12:03:09.000,iam.amazonaws.com,ListRoles,111122223333 8d3e7842-b7ab-4999-9d7d-c3114f7a6dd7,2022-11-03 12:03:10.000,iam.amazonaws.com,ListRoles,111122223333 6b544edb-af54-4083-9bfe-a14eb359b5f8,2022-11-03 12:03:48.000,s3.amazonaws.com,GetBucketAcl,444455556666 8962b5d3-8dda-458d-b71d-677028f29bdb,2022-11-03 12:06:23.000,s3.amazonaws.com,GetBucketAcl,444455556666
なお、クエリ結果は次の構造で保存されます。
All Buckets Bucket_Name AWSLogs Account_ID; CloudTrail-Lake Query 2022 06 20 Query_ID
引用元:CloudTrail Lake に保存されたクエリ結果を見つける - AWS CloudTrail
ユーザーガイドによると、S3 へのエクスポートのレイテンシーは次の通りです。
平均して、クエリ スキャンが完了した後、S3 バケットに配信されるデータ 1 GB ごとに 6 分のレイテンシーが予想されます。
引用元:クエリを実行してクエリ結果を保存する - AWS CloudTrail
1 時間以上のクエリはタイムアウトになる可能性があり、その場合は S3 にエクスポートされない点に留意する必要があります。
1 時間以上実行されるクエリは、タイムアウトになる場合があります。クエリがタイムアウトする前に処理された部分的な結果を引き続き取得できます。CloudTrail は、部分的なクエリ結果を S3 バケットに配信しません。タイムアウトを回避するには、より狭い時間範囲を指定してクエリを調整し、スキャンされるデータの量を制限します。
引用元:クエリを実行してクエリ結果を保存する - AWS CloudTrail
また、クエリ結果の CSV ファイルは 1 ファイルあたり最大 1 TB となり、1 TB を超える場合はファイルが分割されるようです。
配信されるクエリ結果ファイルの数は、クエリ結果の合計サイズによって異なります。クエリ結果ファイルの最大ファイル サイズは 1 TB です。各クエリ結果ファイルの名前は、result_.csv.gz
number
です。たとえば、クエリ結果の合計サイズが 2 TB の場合、result_1.csv.gz と result_2.csv.gz の 2 つのクエリ結果ファイルが作成されます。
引用元:CloudTrail Lake に保存されたクエリ結果をダウンロードする - AWS CloudTrail
署名の検証
S3 にはクエリ結果の他に署名ファイルresult_sign.json
も保存されており、署名を検証することができます。
署名ファイルは次の構造となります。
{ "version": "1.0", "region": "ap-northeast-1", "files": [ { "fileHashValue": "052b4cd259cef22414fbdc0a6821cb11c0aaf757e07f21818a242c021ffa29ee", "fileName": "result_1.csv.gz" } ], "hashAlgorithm": "SHA-256", "signatureAlgorithm": "SHA256withRSA", "hashSignature": "92788186b60871812fc12f0a65d7e562c33c0315a741214bb2a093828cf93fcb91c4f9532093c7524203844416a44e487cbcf1c09a3538385a3f415957135e84196902be82ff5d900f5c5bb0daf8de6faea86175a5ece68aa9972771e0480496164126b83cb12af31ead1f98cd793bc70f56fb8bbf57622723635052614926df10c72d6df0599cb0525f6182d264b0619e19ff84a9f1ee5bac7b41a6557f7d5db19b411f7f36d1b2aee913287dea76f8865d808cedd6c7f574b38a90437742751fdde6f7b68de45bbf719f84122ebd596e3ac86f7261140b938221dd7242dea36198e0f25c103239a407c0d3b3042fbe22af3c3cec7289252d3b0267fc682877", "publicKeyFingerprint": "93953f189caff2358f6231baabff2226", "queryCompleteTime": "2022-11-04T15:07:11Z" }
署名の構造は次のユーザーガイドで解説されています。
CloudTrail 署名ファイルの構造 - AWS CloudTrail
署名の検証を試してみます。
AWS CLI を利用して、次のユーザーガイドの手順に従って実行します。
コマンドラインを使用したクエリ結果の検証 - AWS CloudTrail
まずはローカルにクエリ結果ファイルと署名ファイルをダウンロードします。
$ aws s3 sync s3://test-cloudtrail-lake-query-results-20221104/AWSLogs/111122223333/CloudTrail-Lake/Query/2022/11/04/f0355626-411d-42a9-8365-339a37a8b8c0/ ./ --region ap-northeast-1 download: s3://test-cloudtrail-lake-query-results-20221104/AWSLogs/111122223333/CloudTrail-Lake/Query/2022/11/04/f0355626-411d-42a9-8365-339a37a8b8c0/result_1.csv.gz to ./result_1.csv.gz download: s3://test-cloudtrail-lake-query-results-20221104/AWSLogs/111122223333/CloudTrail-Lake/Query/2022/11/04/f0355626-411d-42a9-8365-339a37a8b8c0/result_sign.json to ./result_sign.json $ ls result_1.csv.gz result_sign.json
openssl
コマンドによりクエリ結果ファイルresult_1.csv.gz
のハッシュ値を確認します。
$ openssl dgst -sha256 result_1.csv.gz SHA256(result_1.csv.gz)= 052b4cd259cef22414fbdc0a6821cb11c0aaf757e07f21818a242c021ffa29ee
もし実行環境にopenssl
がない場合はインストールする必要があります。例えば、AWS CloudShell では次のコマンドでインストールします。
$ sudo yum install openssl
次に、署名の検証に使用する公開鍵(PEM ファイル)を作成します。
公開鍵は AWS CLI または CloudTrail API により取得します。取得にあたり、署名ファイル内のqueryCompleteTime
とpublicKeyFingerprint
を確認しておきます。
AWS CLI により、公開鍵を取得するコマンドは下記となります。複数の公開鍵が返却される場合があるため、query
オプションを用いてpublicKeyFingerprint
が一致する公開鍵のみを取得しています。
aws cloudtrail list-public-keys \ --start-time "2022-11-03T15:07:11Z" \ --end-time "2022-11-04T15:07:11Z" \ --query PublicKeyList[?Fingerprint==\'93953f189caff2358f6231baabff2226\']
実行結果です。
$ aws cloudtrail list-public-keys --start-time "2022-11-03T15:07:11Z" --end-time "2022-11-04T15:07:11Z" --query PublicKeyList[?Fingerprint==\'93953f189caff2358f6231baabff2226\'] [ { "Value": "MIIBCgKCAQEA+bMJFO+f/gJLFq7vN9v/pOsW07r1f181fiRyOfZ3m/x7w1c61tQxflzPLHOtDS57WXjyhu4cGuFui8VnnWX68SAAew0N2vC/kRbd7ajgFdkv6T3enON3ylXROPPQfYQ/QGazMiomdSSPVJaiIRTjMsOg7QvBo2z8Y6rVMgBEcgnQbp0wFZwGuLiMQqAFjYn9xRrI+p4QdQlhxd1bir0Lg+H00d2MSsem+yKzvSV+4BVYqSwcJ2+SLdZ3wi9ot9iqahwK9zSMz1YG8EcpP/j2YBRt0WMQDEo9tjY2Hcsc+XkdqngDVzDXf//3CeW5LQ6DlPJ7nYY2L4loUylG3rgp7QIDAQAB", "ValidityStartTime": "2022-10-18T00:13:00+00:00", "ValidityEndTime": "2022-11-17T00:13:00+00:00", "Fingerprint": "93953f189caff2358f6231baabff2226" } ]
上記出力のValue
の値を利用して公開鍵(PEM ファイル)を作成します。
$ printf -- "-----BEGIN RSA PUBLIC KEY-----\n%s\n-----END RSA PUBLIC KEY-----" "MIIBCgKCAQEA+bMJFO+f/gJLFq7vN9v/pOsW07r1f181fiRyOfZ3m/x7w1c61tQxflzPLHOtDS57WXjyhu4cGuFui8VnnWX68SAAew0N2vC/kRbd7ajgFdkv6T3enON3ylXROPPQfYQ/QGazMiomdSSPVJaiIRTjMsOg7QvBo2z8Y6rVMgBEcgnQbp0wFZwGuLiMQqAFjYn9xRrI+p4QdQlhxd1bir0Lg+H00d2MSsem+yKzvSV+4BVYqSwcJ2+SLdZ3wi9ot9iqahwK9zSMz1YG8EcpP/j2YBRt0WMQDEo9tjY2Hcsc+XkdqngDVzDXf//3CeW5LQ6DlPJ7nYY2L4loUylG3rgp7QIDAQAB" | fold -w64 >> public_key_pkcs1.pem $ cat public_key_pkcs1.pem -----BEGIN RSA PUBLIC KEY----- MIIBCgKCAQEA+bMJFO+f/gJLFq7vN9v/pOsW07r1f181fiRyOfZ3m/x7w1c61tQx flzPLHOtDS57WXjyhu4cGuFui8VnnWX68SAAew0N2vC/kRbd7ajgFdkv6T3enON3 ylXROPPQfYQ/QGazMiomdSSPVJaiIRTjMsOg7QvBo2z8Y6rVMgBEcgnQbp0wFZwG uLiMQqAFjYn9xRrI+p4QdQlhxd1bir0Lg+H00d2MSsem+yKzvSV+4BVYqSwcJ2+S LdZ3wi9ot9iqahwK9zSMz1YG8EcpP/j2YBRt0WMQDEo9tjY2Hcsc+XkdqngDVzDX f//3CeW5LQ6DlPJ7nYY2L4loUylG3rgp7QIDAQAB -----END RSA PUBLIC KEY-----
PEM ファイルをopenssl
で読み込み可能な X.509 形式に変換します。
$ openssl rsa -RSAPublicKey_in -in public_key_pkcs1.pem -pubout -out public_key_x509.pem writing RSA key $ cat public_key_x509.pem -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+bMJFO+f/gJLFq7vN9v/ pOsW07r1f181fiRyOfZ3m/x7w1c61tQxflzPLHOtDS57WXjyhu4cGuFui8VnnWX6 8SAAew0N2vC/kRbd7ajgFdkv6T3enON3ylXROPPQfYQ/QGazMiomdSSPVJaiIRTj MsOg7QvBo2z8Y6rVMgBEcgnQbp0wFZwGuLiMQqAFjYn9xRrI+p4QdQlhxd1bir0L g+H00d2MSsem+yKzvSV+4BVYqSwcJ2+SLdZ3wi9ot9iqahwK9zSMz1YG8EcpP/j2 YBRt0WMQDEo9tjY2Hcsc+XkdqngDVzDXf//3CeW5LQ6DlPJ7nYY2L4loUylG3rgp 7QIDAQAB -----END PUBLIC KEY-----
署名ファイルのhashSignature
の値から、署名のバイナリファイルを作成します。
$ printf "92788186b60871812fc12f0a65d7e562c33c0315a741214bb2a093828cf93fcb91c4f9532093c7524203844416a44e487cbcf1c09a3538385a3f415957135e84196902be82ff5d900f5c5bb0daf8de6faea86175a5ece68aa9972771e0480496164126b83cb12af31ead1f98cd793bc70f56fb8bbf57622723635052614926df10c72d6df0599cb0525f6182d264b0619e19ff84a9f1ee5bac7b41a6557f7d5db19b411f7f36d1b2aee913287dea76f8865d808cedd6c7f574b38a90437742751fdde6f7b68de45bbf719f84122ebd596e3ac86f7261140b938221dd7242dea36198e0f25c103239a407c0d3b3042fbe22af3c3cec7289252d3b0267fc682877" >> signature $ xxd -r -p signature signature.bin
クエリ結果ファイルのハッシュ値を格納するhash_list_file
を作成します。今回の例では、クエリ結果ファイルは 1 ファイルのみのため、ハッシュ値も 1 つとなります。
$ printf "052b4cd259cef22414fbdc0a6821cb11c0aaf757e07f21818a242c021ffa29ee" >> hash_list_file
openssl
コマンドにより、署名の検証を行います。
$ openssl dgst -sha256 -verify public_key_x509.pem -signature signature.bin hash_list_file Verified OK
検証結果は OK です!
以上で、検証作業は終了です。
さいごに
AWS CloudTrail Lake のクエリ結果を S3 にエクスポートできるアップデートの紹介でした。このアップデートにより、Amazon QuickSight やサードパーティの BI ツールによる可視化などの連携が行いやすくなりました。ただし、1 時間以上のクエリは S3 にエクスポートされないなど、いくつか注意が必要な点もありました。
これからの AWS CloudTrail Lake のアップデートも楽しみです。